home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / tar-1_11.lha / tar-1.11.2 / port.c < prev    next >
C/C++ Source or Header  |  1992-10-01  |  26KB  |  1,257 lines

  1. /* Supporting routines which may sometimes be missing.
  2.    Copyright (C) 1988, 1992 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdio.h>
  21. #include <sys/types.h>
  22. #include <signal.h>
  23. #include <errno.h>
  24. #ifndef STDC_HEADERS
  25. extern int errno;
  26. #endif
  27.  
  28. #ifdef BSD42
  29. #include <sys/file.h>
  30. #else
  31. #ifndef V7
  32. #include <fcntl.h>
  33. #endif
  34. #endif
  35.  
  36. #include "tar.h"
  37. #include "port.h"
  38.  
  39. extern long baserec;
  40.  
  41. /* All machine-dependent #ifdefs should appear here, instead of
  42.    being scattered through the file.  For UN*X systems, it is better to
  43.    figure out what is needed in the configure script, for most of the
  44.    features. */
  45.  
  46. #ifdef __MSDOS__
  47. char TTY_NAME[] = "con";
  48. #define HAVE_STRSTR
  49. #define HAVE_RENAME
  50. #define HAVE_MKDIR
  51. #else
  52. char TTY_NAME[] = "/dev/tty";
  53. #endif
  54.  
  55. /* End of system-dependent #ifdefs */
  56.  
  57.  
  58. #ifndef HAVE_VALLOC
  59. /*
  60.  * valloc() does a malloc() on a page boundary.  On some systems,
  61.  * this can make large block I/O more efficient.
  62.  */
  63. char *
  64. valloc (size)
  65.      unsigned size;
  66. {
  67.   return (malloc (size));
  68. }
  69.  
  70. #endif /* !HAVE_VALLOC */
  71.  
  72. #ifndef HAVE_MKDIR
  73. /*
  74.  * Written by Robert Rother, Mariah Corporation, August 1985.
  75.  *
  76.  * If you want it, it's yours.  All I ask in return is that if you
  77.  * figure out how to do this in a Bourne Shell script you send me
  78.  * a copy.
  79.  *                    sdcsvax!rmr or rmr@uscd
  80.  *
  81.  * Severely hacked over by John Gilmore to make a 4.2BSD compatible
  82.  * subroutine.    11Mar86; hoptoad!gnu
  83.  *
  84.  * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
  85.  * subroutine didn't return EEXIST.  It does now.
  86.  */
  87.  
  88. /*
  89.  * Make a directory.
  90.  */
  91. int
  92. mkdir (dpath, dmode)
  93.      char *dpath;
  94.      int dmode;
  95. {
  96.   int cpid, status;
  97.   struct stat statbuf;
  98.  
  99.   if (stat (dpath, &statbuf) == 0)
  100.     {
  101.       errno = EEXIST;        /* Stat worked, so it already exists */
  102.       return -1;
  103.     }
  104.  
  105.   /* If stat fails for a reason other than non-existence, return error */
  106.   if (errno != ENOENT)
  107.     return -1;
  108.  
  109.   switch (cpid = fork ())
  110.     {
  111.  
  112.     case -1:            /* Error in fork() */
  113.       return (-1);        /* Errno is set already */
  114.  
  115.     case 0:            /* Child process */
  116.       /*
  117.          * Cheap hack to set mode of new directory.  Since this
  118.          * child process is going away anyway, we zap its umask.
  119.          * FIXME, this won't suffice to set SUID, SGID, etc. on this
  120.          * directory.  Does anybody care?
  121.          */
  122.       status = umask (0);    /* Get current umask */
  123.       status = umask (status | (0777 & ~dmode));    /* Set for mkdir */
  124.       execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
  125.       _exit (-1);        /* Can't exec /bin/mkdir */
  126.  
  127.     default:            /* Parent process */
  128.       while (cpid != wait (&status));    /* Wait for kid to finish */
  129.     }
  130.  
  131.   if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
  132.     {
  133.       errno = EIO;        /* We don't know why, but */
  134.       return -1;        /* /bin/mkdir failed */
  135.     }
  136.  
  137.   return 0;
  138. }
  139.  
  140. int
  141. rmdir (dpath)
  142.      char *dpath;
  143. {
  144.   int cpid, status;
  145.   struct stat statbuf;
  146.  
  147.   if (stat (dpath, &statbuf) != 0)
  148.     {
  149.       /* Stat just set errno.  We don't have to */
  150.       return -1;
  151.     }
  152.  
  153.   switch (cpid = fork ())
  154.     {
  155.  
  156.     case -1:            /* Error in fork() */
  157.       return (-1);        /* Errno is set already */
  158.  
  159.     case 0:            /* Child process */
  160.       execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
  161.       _exit (-1);        /* Can't exec /bin/mkdir */
  162.  
  163.     default:            /* Parent process */
  164.       while (cpid != wait (&status));    /* Wait for kid to finish */
  165.     }
  166.  
  167.   if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
  168.     {
  169.       errno = EIO;        /* We don't know why, but */
  170.       return -1;        /* /bin/mkdir failed */
  171.     }
  172.  
  173.   return 0;
  174. }
  175.  
  176. #endif /* !HAVE_MKDIR */
  177.  
  178. #ifndef HAVE_RENAME
  179. /* Rename file FROM to file TO.
  180.    Return 0 if successful, -1 if not. */
  181.  
  182. int
  183. rename (from, to)
  184.      char *from;
  185.      char *to;
  186. {
  187.   struct stat from_stats;
  188.  
  189.   if (stat (from, &from_stats))
  190.     return -1;
  191.  
  192.   if (unlink (to) && errno != ENOENT)
  193.     return -1;
  194.  
  195.   if (link (from, to))
  196.     return -1;
  197.  
  198.   if (unlink (from) && errno != ENOENT)
  199.     {
  200.       unlink (to);
  201.       return -1;
  202.     }
  203.  
  204.   return 0;
  205. }
  206.  
  207. #endif /* !HAVE_RENAME */
  208.  
  209. #ifdef minix
  210. /* Minix has bcopy but not bzero, and no memset.  Thanks, Andy. */
  211. void
  212. bzero (s1, n)
  213.      register char *s1;
  214.      register int n;
  215. {
  216.   while (n--)
  217.     *s1++ = '\0';
  218. }
  219.  
  220. /* It also has no bcmp() */
  221. int
  222. bcmp (s1, s2, n)
  223.      register char *s1, *s2;
  224.      register int n;
  225. {
  226.   for (; n--; ++s1, ++s2)
  227.     {
  228.       if (*s1 != *s2)
  229.     return *s1 - *s2;
  230.     }
  231.   return 0;
  232. }
  233.  
  234. /*
  235.  * Groan, Minix doesn't have execlp either!
  236.  *
  237.  * execlp(file,arg0,arg1...argn,(char *)NULL)
  238.  * exec a program, automatically searching for the program through
  239.  * all the directories on the PATH.
  240.  *
  241.  * This version is naive about variable argument lists, it assumes
  242.  * a straightforward C calling sequence.  If your system has odd stacks
  243.  * *and* doesn't have execlp, YOU get to fix it.
  244.  */
  245. int
  246. execlp (filename, arg0)
  247.      char *filename, *arg0;
  248. {
  249.   register char *p, *path;
  250.   register char *fnbuffer;
  251.   char **argstart = &arg0;
  252.   struct stat statbuf;
  253.   extern char **environ;
  254.  
  255.   if ((p = getenv ("PATH")) == NULL)
  256.     {
  257.       /* couldn't find path variable -- try to exec given filename */
  258.       return execve (filename, argstart, environ);
  259.     }
  260.  
  261.   /*
  262.      * make a place to build the filename.  We malloc larger than we
  263.      * need, but we know it will fit in this.
  264.      */
  265.   fnbuffer = malloc (strlen (p) + 1 + strlen (filename));
  266.   if (fnbuffer == NULL)
  267.     {
  268.       errno = ENOMEM;
  269.       return -1;
  270.     }
  271.  
  272.   /*
  273.      * try each component of the path to see if the file's there
  274.      * and executable.
  275.      */
  276.   for (path = p; path; path = p)
  277.     {
  278.       /* construct full path name to try */
  279.       if ((p = index (path, ':')) == NULL)
  280.     {
  281.       strcpy (fnbuffer, path);
  282.     }
  283.       else
  284.     {
  285.       strncpy (fnbuffer, path, p - path);
  286.       fnbuffer[p - path] = '\0';
  287.       p++;            /* Skip : for next time */
  288.     }
  289.       if (strlen (fnbuffer) != 0)
  290.     strcat (fnbuffer, "/");
  291.       strcat (fnbuffer, filename);
  292.  
  293.       /* check to see if file is there and is a normal file */
  294.       if (stat (fnbuffer, &statbuf) < 0)
  295.     {
  296.       if (errno == ENOENT)
  297.         continue;        /* file not there,keep on looking */
  298.       else
  299.         goto fail;        /* failed for some reason, return */
  300.     }
  301.       if (!S_ISREG (statbuf.st_mode))
  302.     continue;
  303.  
  304.       if (execve (fnbuffer, argstart, environ) < 0
  305.       && errno != ENOENT
  306.       && errno != ENOEXEC)
  307.     {
  308.       /* failed, for some other reason besides "file
  309.              * not found" or "not a.out format"
  310.              */
  311.       goto fail;
  312.     }
  313.  
  314.       /*
  315.          * If we got error ENOEXEC, the file is executable but is
  316.          * not an object file.  Try to execute it as a shell script,
  317.          * returning error if we can't execute /bin/sh.
  318.          *
  319.          * FIXME, this code is broken in several ways.  Shell
  320.          * scripts should not in general be executed by the user's
  321.          * SHELL variable program.  On more mature systems, the
  322.          * script can specify with #!/bin/whatever.  Also, this
  323.          * code clobbers argstart[-1] if the exec of the shell
  324.          * fails.
  325.          */
  326.       if (errno == ENOEXEC)
  327.     {
  328.       char *shell;
  329.  
  330.       /* Try to execute command "sh arg0 arg1 ..." */
  331.       if ((shell = getenv ("SHELL")) == NULL)
  332.         shell = "/bin/sh";
  333.       argstart[-1] = shell;
  334.       argstart[0] = fnbuffer;
  335.       execve (shell, &argstart[-1], environ);
  336.       goto fail;        /* Exec didn't work */
  337.     }
  338.  
  339.       /*
  340.          * If we succeeded, the execve() doesn't return, so we
  341.          * can only be here is if the file hasn't been found yet.
  342.          * Try the next place on the path.
  343.          */
  344.     }
  345.  
  346.   /* all attempts failed to locate the file.  Give up. */
  347.   errno = ENOENT;
  348.  
  349. fail:
  350.   free (fnbuffer);
  351.   return -1;
  352. }
  353.  
  354. #endif /* minix */
  355.  
  356.  
  357. #ifdef EMUL_OPEN3
  358. #include "open3.h"
  359. /*
  360.  * open3 -- routine to emulate the 3-argument open system
  361.  * call that is present in most modern Unix systems.
  362.  * This version attempts to support all the flag bits except for O_NDELAY
  363.  * and O_APPEND, which are silently ignored.  The emulation is not as efficient
  364.  * as the real thing (at worst, 4 system calls instead of one), but there's
  365.  * not much I can do about that.
  366.  *
  367.  * Written 6/10/87 by rmtodd@uokmax
  368.  *
  369.  * open3(path, flag, mode)
  370.  * Attempts to open the file specified by
  371.  * the given pathname.  The following flag bits (#defined in tar.h)
  372.  * specify options to the routine:
  373.  *    O_RDONLY    file open for read only
  374.  *    O_WRONLY    file open for write only
  375.  *    O_RDWR        file open for both read & write
  376.  * (Needless to say, you should only specify one of the above).
  377.  *     O_CREAT        file is created with specified mode if it needs to be.
  378.  *    O_TRUNC        if file exists, it is truncated to 0 bytes
  379.  *    O_EXCL        used with O_CREAT--routine returns error if file exists
  380.  * Function returns file descriptor if successful, -1 and errno if not.
  381.  */
  382.  
  383. /*
  384.  * array to give arguments to access for various modes
  385.  * FIXME, this table depends on the specific integer values of O_XXX,
  386.  * and also contains integers (args to 'access') that should be #define's.
  387.  */
  388. static int modes[] =
  389. {
  390.   04,                /* O_RDONLY */
  391.   02,                /* O_WRONLY */
  392.   06,                /* O_RDWR */
  393.   06,                /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
  394. };
  395.  
  396. /* Shut off the automatic emulation of open(), we'll need it. */
  397. #undef open
  398.  
  399. int
  400. open3 (path, flags, mode)
  401.      char *path;
  402.      int flags, mode;
  403. {
  404.   int exists = 1;
  405.   int call_creat = 0;
  406.   int fd;
  407.   /*
  408.      * We actually do the work by calling the open() or creat() system
  409.      * call, depending on the flags.  Call_creat is true if we will use
  410.      * creat(), false if we will use open().
  411.      */
  412.  
  413.   /*
  414.      * See if the file exists and is accessible in the requested mode.
  415.      *
  416.      * Strictly speaking we shouldn't be using access, since access checks
  417.      * against real uid, and the open call should check against euid.
  418.      * Most cases real uid == euid, so it won't matter.   FIXME.
  419.      * FIXME, the construction "flags & 3" and the modes table depends
  420.      * on the specific integer values of the O_XXX #define's.  Foo!
  421.      */
  422.   if (access (path, modes[flags & 3]) < 0)
  423.     {
  424.       if (errno == ENOENT)
  425.     {
  426.       /* the file does not exist */
  427.       exists = 0;
  428.     }
  429.       else
  430.     {
  431.       /* probably permission violation */
  432.       if (flags & O_EXCL)
  433.         {
  434.           /* Oops, the file exists, we didn't want it. */
  435.           /* No matter what the error, claim EEXIST. */
  436.           errno = EEXIST;
  437.         }
  438.       return -1;
  439.     }
  440.     }
  441.  
  442.   /* if we have the O_CREAT bit set, check for O_EXCL */
  443.   if (flags & O_CREAT)
  444.     {
  445.       if ((flags & O_EXCL) && exists)
  446.     {
  447.       /* Oops, the file exists and we didn't want it to. */
  448.       errno = EEXIST;
  449.       return -1;
  450.     }
  451.       /*
  452.          * If the file doesn't exist, be sure to call creat() so that
  453.          * it will be created with the proper mode.
  454.          */
  455.       if (!exists)
  456.     call_creat = 1;
  457.     }
  458.   else
  459.     {
  460.       /* If O_CREAT isn't set and the file doesn't exist, error. */
  461.       if (!exists)
  462.     {
  463.       errno = ENOENT;
  464.       return -1;
  465.     }
  466.     }
  467.  
  468.   /*
  469.      * If the O_TRUNC flag is set and the file exists, we want to call
  470.      * creat() anyway, since creat() guarantees that the file will be
  471.      * truncated and open()-for-writing doesn't.
  472.      * (If the file doesn't exist, we're calling creat() anyway and the
  473.      * file will be created with zero length.)
  474.      */
  475.   if ((flags & O_TRUNC) && exists)
  476.     call_creat = 1;
  477.   /* actually do the call */
  478.   if (call_creat)
  479.     {
  480.       /*
  481.          * call creat.  May have to close and reopen the file if we
  482.          * want O_RDONLY or O_RDWR access -- creat() only gives
  483.          * O_WRONLY.
  484.          */
  485.       fd = creat (path, mode);
  486.       if (fd < 0 || (flags & O_WRONLY))
  487.     return fd;
  488.       if (close (fd) < 0)
  489.     return -1;
  490.       /* Fall out to reopen the file we've created */
  491.     }
  492.  
  493.   /*
  494.      * calling old open, we strip most of the new flags just in case.
  495.      */
  496.   return open (path, flags & (O_RDONLY | O_WRONLY | O_RDWR | O_BINARY));
  497. }
  498.  
  499. #endif /* EMUL_OPEN3 */
  500.  
  501. #ifndef HAVE_MKNOD
  502. #ifdef __MSDOS__
  503. typedef int dev_t;
  504. #endif
  505. /* Fake mknod by complaining */
  506. int
  507. mknod (path, mode, dev)
  508.      char *path;
  509.      unsigned short mode;
  510.      dev_t dev;
  511. {
  512.   int fd;
  513.  
  514.   errno = ENXIO;        /* No such device or address */
  515.   return -1;            /* Just give an error */
  516. }
  517.  
  518. /* Fake links by copying */
  519. int
  520. link (path1, path2)
  521.      char *path1;
  522.      char *path2;
  523. {
  524.   char buf[256];
  525.   int ifd, ofd;
  526.   int nrbytes;
  527.   int nwbytes;
  528.  
  529.   fprintf (stderr, "%s: %s: cannot link to %s, copying instead\n",
  530.        tar, path1, path2);
  531.   if ((ifd = open (path1, O_RDONLY | O_BINARY)) < 0)
  532.     return -1;
  533.   if ((ofd = creat (path2, 0666)) < 0)
  534.     return -1;
  535.   setmode (ofd, O_BINARY);
  536.   while ((nrbytes = read (ifd, buf, sizeof (buf))) > 0)
  537.     {
  538.       if ((nwbytes = write (ofd, buf, nrbytes)) != nrbytes)
  539.     {
  540.       nrbytes = -1;
  541.       break;
  542.     }
  543.     }
  544.   /* Note use of "|" rather than "||" below: we want to close
  545.      * the files even if an error occurs.
  546.      */
  547.   if ((nrbytes < 0) | (0 != close (ifd)) | (0 != close (ofd)))
  548.     {
  549.       unlink (path2);
  550.       return -1;
  551.     }
  552.   return 0;
  553. }
  554.  
  555. /* everyone owns everything on MS-DOS (or is it no one owns anything?) */
  556. int
  557. chown (path, uid, gid)
  558.      char *path;
  559.      int uid;
  560.      int gid;
  561. {
  562.   return 0;
  563. }
  564.  
  565. int
  566. geteuid ()
  567. {
  568.   return 0;
  569. }
  570.  
  571. #endif /* !HAVE_MKNOD */
  572.  
  573. #ifdef __TURBOC__
  574. #include <time.h>
  575. #include <fcntl.h>
  576. #include <io.h>
  577.  
  578. struct utimbuf
  579. {
  580.   time_t actime;        /* Access time. */
  581.   time_t modtime;        /* Modification time. */
  582. };
  583.  
  584. int
  585. utime (char *filename, struct utimbuf *utb)
  586. {
  587.   struct tm *tm;
  588.   struct ftime filetime;
  589.   time_t when;
  590.   int fd;
  591.   int status;
  592.  
  593.   if (utb == 0)
  594.     when = time (0);
  595.   else
  596.     when = utb->modtime;
  597.  
  598.   fd = _open (filename, O_RDWR);
  599.   if (fd == -1)
  600.     return -1;
  601.  
  602.   tm = localtime (&when);
  603.   if (tm->tm_year < 80)
  604.     filetime.ft_year = 0;
  605.   else
  606.     filetime.ft_year = tm->tm_year - 80;
  607.   filetime.ft_month = tm->tm_mon + 1;
  608.   filetime.ft_day = tm->tm_mday;
  609.   if (tm->tm_hour < 0)
  610.     filetime.ft_hour = 0;
  611.   else
  612.     filetime.ft_hour = tm->tm_hour;
  613.   filetime.ft_min = tm->tm_min;
  614.   filetime.ft_tsec = tm->tm_sec / 2;
  615.  
  616.   status = setftime (fd, &filetime);
  617.   _close (fd);
  618.   return status;
  619. }
  620.  
  621. #endif /* __TURBOC__ */
  622.  
  623. /* Stash argv[0] here so panic will know what the program is called */
  624. char *myname = 0;
  625.  
  626. void
  627. panic (s)
  628.      char *s;
  629. {
  630.   if (myname)
  631.     fprintf (stderr, "%s:", myname);
  632.   fprintf (stderr, s);
  633.   putc ('\n', stderr);
  634.   exit (12);
  635. }
  636.  
  637.  
  638. PTR
  639. ck_malloc (size)
  640.      size_t size;
  641. {
  642.   PTR ret;
  643.  
  644.   if (!size)
  645.     size++;
  646.   ret = malloc (size);
  647.   if (ret == 0)
  648.     panic ("Couldn't allocate memory");
  649.   return ret;
  650. }
  651.  
  652. /* Used by alloca.c and bison.simple. */
  653. char *
  654. xmalloc (size)
  655.      size_t size;
  656. {
  657.   return (char *) ck_malloc (size);
  658. }
  659.  
  660. PTR
  661. ck_realloc (ptr, size)
  662.      PTR ptr;
  663.      size_t size;
  664. {
  665.   PTR ret;
  666.  
  667.   if (!ptr)
  668.     ret = ck_malloc (size);
  669.   else
  670.     ret = realloc (ptr, size);
  671.   if (ret == 0)
  672.     panic ("Couldn't re-allocate memory");
  673.   return ret;
  674. }
  675.  
  676. /* Implement a variable sized buffer of 'stuff'.  We don't know what it is,
  677.    nor do we care, as long as it doesn't mind being aligned on a char boundry.
  678.  */
  679.  
  680. struct buffer
  681.   {
  682.     int allocated;
  683.     int length;
  684.     char *b;
  685.   };
  686.  
  687. #define MIN_ALLOCATE 50
  688.  
  689. char *
  690. init_buffer ()
  691. {
  692.   struct buffer *b;
  693.  
  694.   b = (struct buffer *) ck_malloc (sizeof (struct buffer));
  695.   b->allocated = MIN_ALLOCATE;
  696.   b->b = (char *) ck_malloc (MIN_ALLOCATE);
  697.   b->length = 0;
  698.   return (char *) b;
  699. }
  700.  
  701. void
  702. flush_buffer (bb)
  703.      char *bb;
  704. {
  705.   struct buffer *b;
  706.  
  707.   b = (struct buffer *) bb;
  708.   free (b->b);
  709.   b->b = 0;
  710.   b->allocated = 0;
  711.   b->length = 0;
  712.   free ((void *) b);
  713. }
  714.  
  715. void
  716. add_buffer (bb, p, n)
  717.      char *bb;
  718.      char *p;
  719.      int n;
  720. {
  721.   struct buffer *b;
  722.  
  723.   b = (struct buffer *) bb;
  724.   if (b->length + n > b->allocated)
  725.     {
  726.       b->allocated = b->length + n + MIN_ALLOCATE;
  727.       b->b = (char *) ck_realloc (b->b, b->allocated);
  728.     }
  729.   bcopy (p, b->b + b->length, n);
  730.   b->length += n;
  731. }
  732.  
  733. char *
  734. get_buffer (bb)
  735.      char *bb;
  736. {
  737.   struct buffer *b;
  738.  
  739.   b = (struct buffer *) bb;
  740.   return b->b;
  741. }
  742.  
  743. char *
  744. merge_sort (list, n, off, cmp)
  745.      char *list;
  746.      int (*cmp) ();
  747.      unsigned n;
  748.      int off;
  749. {
  750.   char *ret;
  751.  
  752.   char *alist, *blist;
  753.   unsigned alength, blength;
  754.  
  755.   char *tptr;
  756.   int tmp;
  757.   char **prev;
  758. #define NEXTOF(ptr)    (* ((char **)(((char *)(ptr))+off) ) )
  759.   if (n == 1)
  760.     return list;
  761.   if (n == 2)
  762.     {
  763.       if ((*cmp) (list, NEXTOF (list)) > 0)
  764.     {
  765.       ret = NEXTOF (list);
  766.       NEXTOF (ret) = list;
  767.       NEXTOF (list) = 0;
  768.       return ret;
  769.     }
  770.       return list;
  771.     }
  772.   alist = list;
  773.   alength = (n + 1) / 2;
  774.   blength = n / 2;
  775.   for (tptr = list, tmp = (n - 1) / 2; tmp; tptr = NEXTOF (tptr), tmp--)
  776.     ;
  777.   blist = NEXTOF (tptr);
  778.   NEXTOF (tptr) = 0;
  779.  
  780.   alist = merge_sort (alist, alength, off, cmp);
  781.   blist = merge_sort (blist, blength, off, cmp);
  782.   prev = &ret;
  783.   for (; alist && blist;)
  784.     {
  785.       if ((*cmp) (alist, blist) < 0)
  786.     {
  787.       tptr = NEXTOF (alist);
  788.       *prev = alist;
  789.       prev = &(NEXTOF (alist));
  790.       alist = tptr;
  791.     }
  792.       else
  793.     {
  794.       tptr = NEXTOF (blist);
  795.       *prev = blist;
  796.       prev = &(NEXTOF (blist));
  797.       blist = tptr;
  798.     }
  799.     }
  800.   if (alist)
  801.     *prev = alist;
  802.   else
  803.     *prev = blist;
  804.  
  805.   return ret;
  806. }
  807.  
  808. void
  809. ck_close (fd)
  810.      int fd;
  811. {
  812.   if (close (fd) < 0)
  813.     {
  814.       msg_perror ("can't close a file #%d", fd);
  815.       exit (EX_SYSTEM);
  816.     }
  817. }
  818.  
  819. #include <ctype.h>
  820.  
  821. /* Quote_copy_string is like quote_string, but instead of modifying the
  822.    string in place, it malloc-s a copy  of the string, and returns that.
  823.    If the string does not have to be quoted, it returns the NULL string.
  824.    The allocated copy can, of course, be freed with free() after the
  825.    caller is done with it.
  826.  */
  827. char *
  828. quote_copy_string (string)
  829.      char *string;
  830. {
  831.   char *from_here;
  832.   char *to_there = 0;
  833.   char *copy_buf = 0;
  834.   int c;
  835.   int copying = 0;
  836.  
  837.   from_here = string;
  838.   while (*from_here)
  839.     {
  840.       c = *from_here++;
  841.       if (c == '\\')
  842.     {
  843.       if (!copying)
  844.         {
  845.           int n;
  846.  
  847.           n = (from_here - string) - 1;
  848.           copying++;
  849.           copy_buf = (char *) malloc (n + 5 + strlen (from_here) * 4);
  850.           if (!copy_buf)
  851.         return 0;
  852.           bcopy (string, copy_buf, n);
  853.           to_there = copy_buf + n;
  854.         }
  855.       *to_there++ = '\\';
  856.       *to_there++ = '\\';
  857.     }
  858.       else if (isprint (c))
  859.     {
  860.       if (copying)
  861.         *to_there++ = c;
  862.     }
  863.       else
  864.     {
  865.       if (!copying)
  866.         {
  867.           int n;
  868.  
  869.           n = (from_here - string) - 1;
  870.           copying++;
  871.           copy_buf = (char *) malloc (n + 5 + strlen (from_here) * 4);
  872.           if (!copy_buf)
  873.         return 0;
  874.           bcopy (string, copy_buf, n);
  875.           to_there = copy_buf + n;
  876.         }
  877.       *to_there++ = '\\';
  878.       if (c == '\n')
  879.         *to_there++ = 'n';
  880.       else if (c == '\t')
  881.         *to_there++ = 't';
  882.       else if (c == '\f')
  883.         *to_there++ = 'f';
  884.       else if (c == '\b')
  885.         *to_there++ = 'b';
  886.       else if (c == '\r')
  887.         *to_there++ = 'r';
  888.       else if (c == '\177')
  889.         *to_there++ = '?';
  890.       else
  891.         {
  892.           to_there[0] = (c >> 6) + '0';
  893.           to_there[1] = ((c >> 3) & 07) + '0';
  894.           to_there[2] = (c & 07) + '0';
  895.           to_there += 3;
  896.         }
  897.     }
  898.     }
  899.   if (copying)
  900.     {
  901.       *to_there = '\0';
  902.       return copy_buf;
  903.     }
  904.   return (char *) 0;
  905. }
  906.  
  907.  
  908. /* Un_quote_string takes a quoted c-string (like those produced by
  909.    quote_string or quote_copy_string and turns it back into the
  910.    un-quoted original.  This is done in place.
  911.  */
  912.  
  913. /* There is no un-quote-copy-string.  Write it yourself */
  914.  
  915. char *
  916. un_quote_string (string)
  917.      char *string;
  918. {
  919.   char *ret;
  920.   char *from_here;
  921.   char *to_there;
  922.   int tmp;
  923.  
  924.   ret = string;
  925.   to_there = string;
  926.   from_here = string;
  927.   while (*from_here)
  928.     {
  929.       if (*from_here != '\\')
  930.     {
  931.       if (from_here != to_there)
  932.         *to_there++ = *from_here++;
  933.       else
  934.         from_here++, to_there++;
  935.       continue;
  936.     }
  937.       switch (*++from_here)
  938.     {
  939.     case '\\':
  940.       *to_there++ = *from_here++;
  941.       break;
  942.     case 'n':
  943.       *to_there++ = '\n';
  944.       from_here++;
  945.       break;
  946.     case 't':
  947.       *to_there++ = '\t';
  948.       from_here++;
  949.       break;
  950.     case 'f':
  951.       *to_there++ = '\f';
  952.       from_here++;
  953.       break;
  954.     case 'b':
  955.       *to_there++ = '\b';
  956.       from_here++;
  957.       break;
  958.     case 'r':
  959.       *to_there++ = '\r';
  960.       from_here++;
  961.       break;
  962.     case '?':
  963.       *to_there++ = 0177;
  964.       from_here++;
  965.       break;
  966.     case '0':
  967.     case '1':
  968.     case '2':
  969.     case '3':
  970.     case '4':
  971.     case '5':
  972.     case '6':
  973.     case '7':
  974.       tmp = *from_here - '0';
  975.       from_here++;
  976.       if (*from_here < '0' || *from_here > '7')
  977.         {
  978.           *to_there++ = tmp;
  979.           break;
  980.         }
  981.       tmp = tmp * 8 + *from_here - '0';
  982.       from_here++;
  983.       if (*from_here < '0' || *from_here > '7')
  984.         {
  985.           *to_there++ = tmp;
  986.           break;
  987.         }
  988.       tmp = tmp * 8 + *from_here - '0';
  989.       from_here++;
  990.       *to_there = tmp;
  991.       break;
  992.     default:
  993.       ret = 0;
  994.       *to_there++ = '\\';
  995.       *to_there++ = *from_here++;
  996.       break;
  997.     }
  998.     }
  999.   if (*to_there)
  1000.     *to_there++ = '\0';
  1001.   return ret;
  1002. }
  1003.  
  1004. #ifndef __MSDOS__
  1005. void 
  1006. ck_pipe (pipes)
  1007.      int *pipes;
  1008. {
  1009.   if (pipe (pipes) < 0)
  1010.     {
  1011.       msg_perror ("can't open a pipe");
  1012.       exit (EX_SYSTEM);
  1013.     }
  1014. }
  1015. #endif /* !__MSDOS__ */
  1016.  
  1017. #ifndef HAVE_STRSTR
  1018. /*
  1019.  * strstr - find first occurrence of wanted in s
  1020.  */
  1021.  
  1022. char *                /* found string, or NULL if none */
  1023. strstr (s, wanted)
  1024.      char *s;
  1025.      char *wanted;
  1026. {
  1027.   register char *scan;
  1028.   register size_t len;
  1029.   register char firstc;
  1030.  
  1031.   if (*wanted == '\0')
  1032.     return (char *) 0;
  1033.   /*
  1034.      * The odd placement of the two tests is so "" is findable.
  1035.      * Also, we inline the first char for speed.
  1036.      * The ++ on scan has been moved down for optimization.
  1037.      */
  1038.   firstc = *wanted;
  1039.   len = strlen (wanted);
  1040.   for (scan = s; *scan != firstc || strncmp (scan, wanted, len) != 0;)
  1041.     if (*scan++ == '\0')
  1042.       return (char *) 0;
  1043.   return scan;
  1044. }
  1045.  
  1046. #endif /* !HAVE_STRSTR */
  1047.  
  1048. #ifndef HAVE_FTRUNCATE
  1049.  
  1050. #ifdef F_CHSIZE
  1051. int
  1052. ftruncate (fd, length)
  1053.      int fd;
  1054.      off_t length;
  1055. {
  1056.   return fcntl (fd, F_CHSIZE, length);
  1057. }
  1058.  
  1059. #else /* !F_CHSIZE */
  1060. #ifdef F_FREESP
  1061. /* code courtesy of William Kucharski, kucharsk@Solbourne.com */
  1062.  
  1063. int
  1064. ftruncate (fd, length)
  1065.      int fd;            /* file descriptor */
  1066.      off_t length;        /* length to set file to */
  1067. {
  1068.   struct flock fl;
  1069.  
  1070.   fl.l_whence = 0;
  1071.   fl.l_len = 0;
  1072.   fl.l_start = length;
  1073.   fl.l_type = F_WRLCK;        /* write lock on file space */
  1074.  
  1075.   /*
  1076.      * This relies on the UNDOCUMENTED F_FREESP argument to
  1077.      * fcntl(2), which truncates the file so that it ends at the
  1078.      * position indicated by fl.l_start.
  1079.      *
  1080.      * Will minor miracles never cease?
  1081.      */
  1082.  
  1083.   if (fcntl (fd, F_FREESP, &fl) < 0)
  1084.     return -1;
  1085.  
  1086.   return 0;
  1087. }
  1088.  
  1089. #else /* !F_FREESP */
  1090.  
  1091. int
  1092. ftruncate (fd, length)
  1093.      int fd;
  1094.      off_t length;
  1095. {
  1096.   errno = EIO;
  1097.   return -1;
  1098. }
  1099.  
  1100. #endif /* !F_FREESP */
  1101. #endif /* !F_CHSIZE */
  1102. #endif /* !HAVE_FTRUNCATE */
  1103.  
  1104.  
  1105. extern FILE *msg_file;
  1106.  
  1107. #if defined (HAVE_VPRINTF) && __STDC__
  1108. #include <stdarg.h>
  1109.  
  1110. void
  1111. msg (char *str,...)
  1112. {
  1113.   va_list args;
  1114.  
  1115.   va_start (args, str);
  1116.   fflush (msg_file);
  1117.   fprintf (stderr, "%s: ", tar);
  1118.   if (f_sayblock)
  1119.     fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
  1120.   vfprintf (stderr, str, args);
  1121.   va_end (args);
  1122.   putc ('\n', stderr);
  1123.   fflush (stderr);
  1124. }
  1125.  
  1126. void
  1127. msg_perror (char *str,...)
  1128. {
  1129.   va_list args;
  1130.   int save_e;
  1131.  
  1132.   save_e = errno;
  1133.   fflush (msg_file);
  1134.   fprintf (stderr, "%s: ", tar);
  1135.   if (f_sayblock)
  1136.     fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
  1137.   va_start (args, str);
  1138.   vfprintf (stderr, str, args);
  1139.   va_end (args);
  1140.   errno = save_e;
  1141.   perror (" ");
  1142.   fflush (stderr);
  1143. }
  1144.  
  1145. #endif /* HAVE_VPRINTF and __STDC__ */
  1146.  
  1147. #if defined(HAVE_VPRINTF) && !__STDC__
  1148. #include <varargs.h>
  1149. void
  1150. msg (str, va_alist)
  1151.      char *str;
  1152.      va_dcl
  1153. {
  1154.   va_list args;
  1155.  
  1156.   fflush (msg_file);
  1157.   fprintf (stderr, "%s: ", tar);
  1158.   if (f_sayblock)
  1159.     fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
  1160.   va_start (args);
  1161.   vfprintf (stderr, str, args);
  1162.   va_end (args);
  1163.   putc ('\n', stderr);
  1164.   fflush (stderr);
  1165. }
  1166.  
  1167. void
  1168. msg_perror (str, va_alist)
  1169.      char *str;
  1170.      va_dcl
  1171. {
  1172.   va_list args;
  1173.   int save_e;
  1174.  
  1175.   save_e = errno;
  1176.   fflush (msg_file);
  1177.   fprintf (stderr, "%s: ", tar);
  1178.   if (f_sayblock)
  1179.     fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
  1180.   va_start (args);
  1181.   vfprintf (stderr, str, args);
  1182.   va_end (args);
  1183.   errno = save_e;
  1184.   perror (" ");
  1185.   fflush (stderr);
  1186. }
  1187.  
  1188. #endif /* HAVE_VPRINTF and not __STDC__ */
  1189.  
  1190. #if !defined(HAVE_VPRINTF) && defined(HAVE_DOPRNT)
  1191. void
  1192. msg (str, args)
  1193.      char *str;
  1194.      int args;
  1195. {
  1196.   fflush (msg_file);
  1197.   fprintf (stderr, "%s: ", tar);
  1198.   if (f_sayblock)
  1199.     fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
  1200.   _doprnt (str, &args, stderr);
  1201.   putc ('\n', stderr);
  1202.   fflush (stderr);
  1203. }
  1204.  
  1205. void
  1206. msg_perror (str, args)
  1207.      char *str;
  1208.      int args;
  1209. {
  1210.   int save_e;
  1211.  
  1212.   save_e = errno;
  1213.   fflush (msg_file);
  1214.   fprintf (stderr, "%s: ", tar);
  1215.   if (f_sayblock)
  1216.     fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
  1217.   _doprnt (str, &args, stderr);
  1218.   errno = save_e;
  1219.   perror (" ");
  1220.   fflush (stderr);
  1221. }
  1222.  
  1223. #endif /* !HAVE_VPRINTF and HAVE_DOPRNT */
  1224.  
  1225. #if !defined(HAVE_VPRINTF) && !defined(HAVE_DOPRNT)
  1226. void 
  1227. msg (str, a1, a2, a3, a4, a5, a6)
  1228.      char *str;
  1229. {
  1230.   fflush (msg_file);
  1231.   fprintf (stderr, "%s: ", tar);
  1232.   if (f_sayblock)
  1233.     fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
  1234.   fprintf (stderr, str, a1, a2, a3, a4, a5, a6);
  1235.   putc ('\n', stderr);
  1236.   fflush (stderr);
  1237. }
  1238.  
  1239. void
  1240. msg_perror (str, a1, a2, a3, a4, a5, a6)
  1241.      char *str;
  1242. {
  1243.   int save_e;
  1244.  
  1245.   save_e = errno;
  1246.   fflush (msg_file);
  1247.   fprintf (stderr, "%s: ", tar);
  1248.   if (f_sayblock)
  1249.     fprintf (stderr, "rec %d: ", baserec + (ar_record - ar_block));
  1250.   fprintf (stderr, str, a1, a2, a3, a4, a5, a6);
  1251.   fprintf (stderr, ": ");
  1252.   errno = save_e;
  1253.   perror (" ");
  1254. }
  1255.  
  1256. #endif /* !HAVE_VPRINTF and !HAVE_DOPRNT */
  1257.